home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / HARDWARE.SWG / 0021_device Driver Lists.pas < prev    next >
Pascal/Delphi Source File  |  1994-01-27  |  6KB  |  201 lines

  1. {
  2. I've posted a working util that lists the Device Drivers that are resident in
  3. memory.  It uses the header record to point to the next driver in the chain
  4. and "walks" the memory chain until an offset end flag is reached.  Hope you
  5. enjoy it and that it isn't too sloppy.  At the end, I have a question that
  6. needs to be answered if you're interested....
  7. }
  8.  
  9. program DevList;
  10.  
  11. { this program walks the device driver memory chain. Each device
  12.   driver points to the next until the ENDFLAG is reached.  I use
  13.   the popular undocumented DOS function $52 to jump to the DOS
  14.   "List of Lists" then $22 bytes beyond that, the first device in
  15.   the chain (NUL) can be found.
  16.  
  17.   Thanks to Ralf Brown and his valuable MS DOS Interrupts List,
  18.   to Timo Salmi, and to the person(?) who wrote the cool
  19.   hex-to-string conversion functions that I use all the time.
  20. }
  21.  
  22. {$M 8192,0,0}
  23.  
  24. uses
  25.   DOS;
  26.  
  27. type
  28.   pstrg = string[9];                { pointer conversion format }
  29.  
  30.   Array8C = array [1..8] of char; { for device and file names }
  31.  
  32.   DevRec = record
  33.     NextDev_ofs  : word; {pointer to next device header, offset value}
  34.     NextDev_seg  : word; {pointer to next device header, segment value}
  35.     Attributes   : word; {Attributes: block or char, IOCTL, etc.}
  36.     Strategy     : word; {pointer to device strategy routine, offset}
  37.     Interrupt    : word; {pointer to device interrupt routine, offset}
  38.     NameDev      : Array8C; {Name if char, or units if block}
  39.   end;
  40.   DevPtr = ^DevRec;
  41.  
  42.   DevFileRec = record
  43.     FileName : Array8C;
  44.   end;
  45.   DevFilePtr = ^DevFileRec;
  46.  
  47. const
  48.   LOL_HEADDEV_NUL  = $22; { offset from "List of Lists"
  49.                             to NUL device header }
  50.   FNAME            = $8;
  51.   ENDFLAG          = $FFFF;
  52.   STDDEVS : array [1..12] of Array8C =
  53.     ('NUL     ', 'CON     ', 'AUX     ', 'PRN     ',
  54.      'CLOCK$  ', 'COM1    ', 'COM2    ', 'COM3    ',
  55.      'COM4    ', 'LPT1    ', 'LPT2    ', 'LPT3    ');
  56.  
  57. var
  58.   r       : registers;
  59.   i,        { index }
  60.   Adjust  : byte;
  61.   Header  : DevPtr;
  62.   DevFile : DevFilePtr;
  63.   Valid,
  64.   Done    : boolean;
  65.  
  66.  
  67. function BinW(Decimal : word) : string;
  68. const
  69.   BINDIGIT : array [0..1] of char = '01';
  70. var
  71.   i     : byte;
  72.   Binar : string;
  73. begin
  74.   fillchar (binar, sizeof(Binar), ' ');
  75.   Binar [0] := chr(16);
  76.   for i := 0 to 15 do
  77.     Binar[16-i] := BINDIGIT[(Decimal shr i) and 1];
  78.   BinW := Binar;
  79. end;
  80.  
  81.  
  82. function HexN (b : byte) : char;        { convert nibble to char }
  83. begin
  84.   b := b and 15;                   { forces to only 4 bits }
  85.   if b > 9 then
  86.      inc(b,7);                    { adjust for hex digits };
  87.   HexN := chr(b+48);              { convert to character }
  88. end;
  89.  
  90.  
  91. function HexB(b : byte) : string;
  92. begin
  93.   HexB := HexN (b shr 4) + HexN (b);  { assemble the nibbles }
  94. end;
  95.  
  96.  
  97. function HexW(w : word) : string;
  98. begin
  99. {$R-}
  100.   hexw := HexB(w shr 8) + HexB(w);  { assemble the bytes }
  101. {$R+}
  102. end;
  103.  
  104.  
  105. function HexL(l : longint) : string;
  106. begin
  107.   HexL := HexW(l shr 16) + HexW(l); { assemble the words }
  108. end;
  109.  
  110.  
  111. function XP(p : pointer) : pstrg;         { display pointer P }
  112. begin
  113.   XP := HexW(seg(p^)) + ':' + HexW(ofs(p^));
  114. end;
  115.  
  116. begin
  117.   assign(output, '');
  118.   rewrite(output);     { allow command line redirection }
  119.   writeln('Device':0, 'Address':12, 'Strat':10, 'Intrpt':8,
  120.           'Attrib':10, 'File Name':23);
  121.   for i := 1 to 69 do
  122.     write('-');
  123.   writeln;
  124.  
  125.   with r do
  126.   begin
  127.     es := 0;
  128.     bx := 0;
  129.     ah := $52;
  130.     { this is an undocumented DOS function call:
  131.       Get pointer to DOS "List of Lists" }
  132.     msdos (r);
  133.     { es and bx now have values }
  134.     if (es = 0) and (bx = 0) then
  135.       halt(0);
  136.  
  137.     Header := ptr(es, bx + LOL_HEADDEV_NUL); { we get NUL dev from this }
  138.   end; {with}
  139.  
  140.   Done := FALSE; { dummy variable to keep the repeat loop going,
  141.                     otherwise would have to duplicate the output
  142.                     routines one more time for the final device. }
  143.   repeat
  144.     with Header^ do
  145.     begin
  146.       Adjust := 0;
  147.       { adjust keeps display columns aligned, bit 15 set is a Character
  148.         device, if clear it is a Block device and 1st byte is # of block
  149.         devs supported}
  150.  
  151.       if boolean ((Attributes shr 15) and 1) = TRUE then
  152.         write (NameDev)
  153.       else
  154.       begin
  155.         write ('BLKdev=', byte (NameDev[1]));
  156.         Adjust := byte (NameDev[1]) div 10;
  157.       end;
  158.  
  159.       write(XP(Header) : 12 - Adjust);
  160.       write(HexW(Strategy) : 7);
  161.       write(HexW(Interrupt) : 7);
  162.       write(HexW(Attributes) : 7, '=');
  163.       write(BinW(Attributes));
  164.  
  165.       { this next section I can't find documented anywhere, but I observed it
  166.         and decided to include it anyway, with MSDOS v5.0, others are unknown.
  167.         The file name's extension isn't saved and doesn't matter, either. }
  168.  
  169.       if ofs(Header^) < FNAME then
  170.       { "borrow" from the segment and give it to the offset }
  171.         DevFile := ptr(seg(Header^) - $1, ofs(Header^) + $10 - FNAME)
  172.       else
  173.         DevFile := ptr(seg(Header^), ofs(Header^) - FNAME);
  174.  
  175.       Valid := TRUE;
  176.       for i := 1 to 12 do
  177.         if DevFile^.FileName = STDDEVS[i] then
  178.           Valid := FALSE;
  179.  
  180.       if Valid then
  181.         for i := 1 to 8 do
  182.           if not (DevFile^.Filename[i] in [' '..'z']) then
  183.             Valid := FALSE;
  184.  
  185.       if {still} Valid then
  186.         write ('  ', DevFile^.FileName);
  187.  
  188.       writeln;
  189.       if NextDev_ofs = ENDFLAG then
  190.         exit; { end of the device chain }
  191.  
  192.       Header := ptr(NextDev_seg, NextDev_ofs);
  193.  
  194.     end; {with}
  195.   until Done;
  196. end.
  197. {
  198. The question: I have seen utils that do this actually give the size of
  199. the driver in memory.  MSD and PMap both do this.  Does anybody know
  200. how I can determine the size of the driver in memory?
  201. }